package com.lyw.GeoLocationClient.service;

import android.content.Context;
import android.os.Looper;
import android.widget.Button;
import android.widget.Toast;
import com.baidu.location.BDLocation;
import com.baidu.mapapi.map.MapView;
import com.baidu.trace.*;
import com.easemob.applib.utils.HXPreferenceUtils;
import com.lyw.GeoLocationClient.App;
import com.lyw.GeoLocationClient.R;
import com.lyw.GeoLocationClient.trackshow.Geofence;
import com.lyw.GeoLocationClient.trackshow.TraceMainActivity;
import com.lyw.GeoLocationClient.utils.LocationCallback;
import timber.log.Timber;

import java.util.HashMap;
import java.util.Map;

public class TraceService {
    private String mUsername;
    private Context mContext;

    /**
     * 轨迹服务
     */
    protected static Trace trace = null;

    /**
     * entity标识
     */
    protected static String entityName = null;

    /**
     * 鹰眼服务ID，开发者创建的鹰眼服务对应的服务ID
     */
    protected static final long serviceId = 110322; // serviceId为开发者创建的鹰眼服务ID

    /**
     * 轨迹服务类型（0 : 不建立socket长连接， 1 : 建立socket长连接但不上传位置数据，2 : 建立socket长连接并上传位置数据）
     */
    private int traceType = 2;

    /**
     * 轨迹服务客户端
     */
    protected static LBSTraceClient client = null;

    /**
     * Entity监听器
     */
    protected static OnEntityListener entityListener = null;

    /**
     * Track监听器
     */
    protected static OnTrackListener trackListener = null;

    private LocationCallback mLocationCallback;
    private boolean isTraceStart;
    private MyAlarmManager alarManager;
    private int mGatherInterval;
    private RefreshThread refreshThread;
    private BDLocation mBDLocation;

    public TraceService(Context mContext) {
        this.mContext = mContext;
        initService();
    }

    public Trace getTrace() {
        return trace;
    }

    public LBSTraceClient getClient() {
        return client;
    }


    private void initService() {
        // 初始化轨迹服务客户端
        client = new LBSTraceClient(mContext);



//        addEntity(entityName, new OnEntityListener() {
//            @Override
//            public void onAddEntityCallback(String s) {
//                Looper.prepare();
//                Timber.d(
//                        "onAddEntityCallback : " + s);
//                Looper.loop();
//            }
//
//            @Override
//            public void onUpdateEntityCallback(String s) {
//                super.onUpdateEntityCallback(s);
//                Timber.d(
//                        "onUpdateEntityCallback : " + s);
//            }
//
//            @Override
//            public void onRequestFailedCallback(String s) {
//                Looper.prepare();
//                Timber.d(
//                        "onRequestFailedCallback : " + s);
//                Looper.loop();
//            }
//        });

    }

    public void addEntity(String entityName, OnEntityListener listener) {
        // 属性名称（格式 : "key1=value1,columnKey2=columnValue2......."）
        addEntity(entityName, "", listener);
    }

    /**
     *
     * @param entityName
     * @param columnKey 属性名称（格式 : "key1=value1,columnKey2=columnValue2......."）
     * @param listener
     */
    public void addEntity(String entityName, String columnKey, OnEntityListener listener) {
        client.addEntity(serviceId, entityName, columnKey, listener);
    }

    public void starTrace(String username, final OnStartTraceListener startTraceListener) {
        if (isTraceStart) {
            Timber.e("is started");
            return;
        }
        // 初始化entity标识
        mUsername = username;
        entityName = mUsername;
        // 初始化轨迹服务
        if (trace == null) {
            trace = new Trace(mContext, serviceId, entityName,
                    traceType);
        }

        setInterval(HXPreferenceUtils.getInstance().getUpdateSpan(), HXPreferenceUtils.getInstance().getUpdateSpan()*10);
        client.startTrace(trace, new OnStartTraceListener() {
            @Override
            public void onTraceCallback(int arg0, String arg1) {
                if (startTraceListener != null) {
                    startTraceListener.onTraceCallback(arg0, arg1);
                }
                if (0 == arg0 || 10006 == arg0 || 10008 == arg0) {
                    isTraceStart = true;
                    startRefreshThread(true);
                }
            }

            @Override
            public void onTracePushCallback(byte b, String s) {
                if (startTraceListener != null) {
                    startTraceListener.onTracePushCallback(b, s);
                }
            }
        });
    }

    private void startRefreshThread(boolean isStart) {
        startAlarm(isStart);
        if (null == refreshThread) {
            refreshThread = new RefreshThread();
        }
        refreshThread.refresh = isStart;
        if (isStart) {
            if (!refreshThread.isAlive()) {
                refreshThread.start();
            }
        } else {
            refreshThread = null;
        }
    }

    public BDLocation getBDLocation() {
        return mBDLocation;
    }

    protected class RefreshThread extends Thread {

        protected boolean refresh = true;

        @Override
        public void run() {
            Timber.d("RefreshThread run");

            while (refresh) {
                // 查询实时轨迹
                queryRealtimeTrack();
                try {
                    Thread.sleep(5 * 1000);
                } catch (InterruptedException e) {
                    Timber.e("线程休眠失败");
                }
            }

        }
    }

    private void queryRealtimeTrack() {
        Timber.d("queryRealtimeTrack");
        client.queryRealtimeLoc(serviceId, mQueryRealTimeTrackCallback);
    }

    private void queryRealtimeTrack(final LocationCallback locationCallback) {
        client.queryRealtimeLoc(serviceId, new OnEntityListener() {

            @Override
            public void onReceiveLocation(TraceLocation traceLocation) {
                Timber.d("onReceiveLocation");
                super.onReceiveLocation(traceLocation);
                if (locationCallback != null) {
                    Timber.d("call back onReceiveLocation");
                    double latitude = traceLocation.getLatitude();
                    double longitude = traceLocation.getLongitude();
                    if (Math.abs(latitude - 0.0) < 0.000001 && Math.abs(longitude - 0.0) < 0.000001) {

                    } else {
                        locationCallback.onReceiveLocation(getBDLocationFromTraceLocation(traceLocation));
                    }
                }
            }

            @Override
            public void onRequestFailedCallback(String s) {

            }
        });
    }

    private OnEntityListener mQueryRealTimeTrackCallback = new OnEntityListener() {

        @Override
        public void onQueryEntityListCallback(String s) {
            Timber.d("onQueryEntityListCallback " + s);
            super.onQueryEntityListCallback(s);
        }

        @Override
        public void onAddEntityCallback(String s) {
            Looper.prepare();

            Timber.d("onAddEntityCallback " + s);
            Looper.loop();
            super.onAddEntityCallback(s);
        }

        @Override
        public void onUpdateEntityCallback(String s) {
            Timber.d("onUpdateEntityCallback " + s);

            super.onUpdateEntityCallback(s);
        }


        @Override
        public void onReceiveLocation(TraceLocation traceLocation) {
            Timber.d("onReceiveLocation");
            super.onReceiveLocation(traceLocation);
            if (mLocationCallback != null) {
                double latitude = traceLocation.getLatitude();
                double longitude = traceLocation.getLongitude();
                if (Math.abs(latitude - 0.0) < 0.000001 && Math.abs(longitude - 0.0) < 0.000001) {

                } else {
                    mLocationCallback.onReceiveLocation(getBDLocationFromTraceLocation(traceLocation));
                }
            }
        }

        @Override
        public void onRequestFailedCallback(String s) {
            Timber.e("onRequestFailedCallback " + s);
        }
    };

    public static boolean isValidTraceLocation(TraceLocation traceLocation) {
        double latitude = traceLocation.getLatitude();
        double longitude = traceLocation.getLongitude();
        return !(Math.abs(latitude - 0.0) < 0.000001 && Math.abs(longitude - 0.0) < 0.000001);
    }

    private BDLocation getBDLocationFromTraceLocation(TraceLocation traceLocation) {
        BDLocation bdLocation = new BDLocation();
        bdLocation.setLatitude(traceLocation.getLatitude());
        bdLocation.setLongitude(traceLocation.getLongitude());
        bdLocation.setRadius((float) traceLocation.getRadius());
        bdLocation.setAltitude(traceLocation.getAltitude());
        bdLocation.setFloor(traceLocation.getFloor());
        bdLocation.setDirection(traceLocation.getDirection());
        bdLocation.setBuildingName(traceLocation.getBuilding());
        bdLocation.setTime(traceLocation.getTime());

        mBDLocation = bdLocation;
        return bdLocation;
    }


    private void startAlarm(boolean b) {
        if (b) {
            alarManager = new MyAlarmManager(mContext);
            alarManager.startAlarm(mGatherInterval*8);
        } else {
            alarManager.stop();
        }
    }


    /**
     * 停止轨迹服务
     */
    public void stopTrace(OnStopTraceListener stopTraceListener) {
        // 通过轨迹服务客户端client停止轨迹服务
        if (stopTraceListener != null) {
            client.stopTrace(trace, stopTraceListener);
            startRefreshThread(false);
        } else {
            client.stopTrace(trace, new OnStopTraceListener() {
                @Override
                public void onStopTraceSuccess() {
                    isTraceStart = false;
                    startRefreshThread(isTraceStart);
                }

                @Override
                public void onStopTraceFailed(int i, String s) {

                }
            });
        }
    }

    private void setInterval(int gatherInterval, int packInterval) {
        Timber.d("setInterval " + gatherInterval + " " + packInterval);
        mGatherInterval = gatherInterval;
        client.setInterval(gatherInterval, packInterval);
    }

    private void setRequestType(int type) {
        client.setProtocolType(type);
    }

    public void setLocationCallback(LocationCallback mLocationCallback) {
        this.mLocationCallback = mLocationCallback;
    }
}
